from django.db import models
import json

# 原代码整体结构清晰，符合 Django 模型定义的规范，但可以从以下几个方面进行优化：
# 1. 添加模型方法：为模型添加一些实用的方法，提高代码的可读性和可维护性。
# 2. 添加索引：对于经常用于查询的字段，添加索引可以提高查询效率。
# 3. 添加注释：为模型和字段添加详细的注释，方便其他开发者理解代码。

class Holiday(models.Model):
    """节假日管理模型"""
    name = models.CharField("节假日名称", max_length=100)
    date = models.DateField("日期", unique=True)
    is_workday = models.BooleanField("是否工作日", default=False)
    description = models.TextField("描述", blank=True)
    created_at = models.DateTimeField("创建时间", auto_now_add=True)

    class Meta:
        verbose_name = "节假日"
        verbose_name_plural = "节假日管理"
        ordering = ['-date']
        indexes = [
            models.Index(fields=['date']),
        ]

    def __str__(self):
        return f"{self.name} ({self.date})"



class ShiftType(models.Model):
    """班次类型模型"""
    name = models.CharField("班次名称", max_length=100)
    code = models.CharField("班次代码", max_length=1, unique=True)
    start_time = models.TimeField("开始时间")
    end_time = models.TimeField("结束时间")
    description = models.TextField("描述", blank=True)

    class Meta:
        verbose_name = "班次类型"
        verbose_name_plural = "班次类型管理"

    def __str__(self):
        return f"{self.name} ({self.start_time}-{self.end_time})"

class Employee(models.Model):
    """员工模型"""
    name = models.CharField("员工姓名", max_length=100)
    position = models.CharField("职位", max_length=100)
    created_at = models.DateTimeField("创建时间", auto_now_add=True)
    preferred_shift = models.ForeignKey(ShiftType, verbose_name="偏好班次", on_delete=models.SET_NULL, blank=True, null=True)
    unavailable_dates = models.JSONField("不可工作日期", default=list, blank=True)
    monthly_rest_days = models.PositiveSmallIntegerField("每月排休天数", default=4)

    class Meta:
        verbose_name = "员工"
        verbose_name_plural = "员工管理"
        indexes = [
            models.Index(fields=['name']),
        ]

    def __str__(self):
        return self.name


    end_time = models.TimeField("结束时间")
    description = models.TextField("描述", blank=True)

    class Meta:
        verbose_name = "班次类型"
        verbose_name_plural = "班次类型管理"

    def __str__(self):
        return f"{self.name} ({self.start_time}-{self.end_time})"

class MonthlySchedule(models.Model):
    """按月排班计划模型"""
    employee = models.ForeignKey(Employee, verbose_name="员工", on_delete=models.CASCADE)
    month = models.DateField("月份")
    created_at = models.DateTimeField("创建时间", auto_now_add=True)

    class Meta:
        verbose_name = "按月排班计划"
        verbose_name_plural = "按月排班计划管理"
        unique_together = ['employee', 'month']

    def __str__(self):
        return f"{self.employee.name} {self.month.strftime('%Y-%m')}"


class Shift(models.Model):
    employee = models.ForeignKey(Employee, verbose_name="员工", on_delete=models.CASCADE)
    shift_type = models.ForeignKey(ShiftType, verbose_name="班次类型", on_delete=models.PROTECT)
    shift_date = models.DateField("排班日期")
    monthly_schedule = models.ForeignKey(MonthlySchedule, verbose_name="按月计划", on_delete=models.CASCADE, null=True, blank=True)
    created_at = models.DateTimeField("创建时间", auto_now_add=True)

    class Meta:
        verbose_name = "排班记录"
        verbose_name_plural = "排班管理"
        ordering = ['-shift_date']
        indexes = [
            models.Index(fields=['employee', 'shift_date']),
        ]

    def __str__(self):
        return f"{self.employee.name} - {self.get_shift_type_display()} - {self.shift_date}"
        
    def check_conflicts(self):
        """检查排班冲突
        返回:
            dict: 包含冲突信息的字典
        """
        conflicts = {}
        
        # 检查同一员工同一天是否已有排班
        existing_shift = Shift.objects.filter(
            employee=self.employee,
            shift_date=self.shift_date
        ).exclude(pk=self.pk).first()
        if existing_shift:
            conflicts['duplicate'] = f"员工{self.employee.name}在{self.shift_date}已有{existing_shift.get_shift_type_display()}排班"
            
        # 检查是否违反员工偏好
        if self.employee.preferred_shift and self.shift_type != self.employee.preferred_shift:
            conflicts['preference'] = f"违反员工偏好: 实际排班{self.get_shift_type_display()}与偏好{self.employee.get_preferred_shift_display()}不符"
            
        # 检查是否在员工不可工作日期
        if str(self.shift_date) in self.employee.unavailable_dates:
            conflicts['unavailable'] = f"员工{self.employee.name}在{self.shift_date}不可工作"
            
        return conflicts
